package com.lyl.mysqlmonitor;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lyl.mysqlmonitor.callback.CallbackManager;
import com.lyl.mysqlmonitor.config.MonitorConfig;
import com.lyl.mysqlmonitor.util.SqlFormatter;
import com.lyl.mysqlmonitor.util.SqlPatterns;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * SQL分析工具类
 * 用于分析SQL语句的索引使用情况
 */
public class SqlAnalyzer {

    private static final Logger LOGGER = LoggerFactory.getLogger(SqlAnalyzer.class);
    // 专用于索引分析结果的Logger
    private static final Logger INDEX_ANALYSIS_LOGGER = LoggerFactory.getLogger(SqlAnalyzer.class.getName() + ".INDEX_ANALYSIS");
    private static final MonitorConfig CONFIG = MonitorConfig.getInstance();
    
    // 用于跟踪当前正在分析的SQL
    private static final ThreadLocal<String> CURRENT_ANALYZING_SQL = new ThreadLocal<>();

    /**
     * 私有构造方法，防止实例化
     */
    private SqlAnalyzer() {
    }

    /**
     * 分析SQL语句
     * @param sql SQL语句
     * @param conn 数据库连接
     */
    public static void analyze(String sql, Connection conn) {
        if (!shouldAnalyze(sql)) {
            return;
        }

        // 检查SQL兼容性
        checkSqlCompatibility(sql);

        try {
            LOGGER.info("正在分析SQL: \n{}", sql);
            
            // 设置当前正在分析的SQL
            CURRENT_ANALYZING_SQL.set(sql);
            
            // 在索引分析日志中记录当前分析的SQL
            INDEX_ANALYSIS_LOGGER.info("===== 分析SQL =====\n{}", sql);
            
            // 调用回调接口的onAnalysisStart方法
            if (CONFIG.hasCallback()) {
                CONFIG.getCallbackManager().notifyAnalysisStart(sql);
            }

            // 根据MySQL版本使用不同的EXPLAIN格式
            String explainSql = SqlFormatter.getExplainSql(sql, CONFIG.isMySQL80Mode() && CONFIG.isProvideOptimizationTips());

            try (Statement explainStmt = conn.createStatement();
                 ResultSet explainRs = explainStmt.executeQuery(explainSql)) {

                processExplainResult(explainRs);
            }
        } catch (SQLException e) {
            LOGGER.error("分析SQL时出错: {}", e.getMessage(), e);
            
            // 调用回调接口的onAnalysisError方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisError(originalSql, "分析SQL时出错: " + e.getMessage(), e);
            }
        } finally {
            // 清除ThreadLocal变量，防止内存泄漏
            CURRENT_ANALYZING_SQL.remove();
        }
    }

    /**
     * 分析预编译SQL语句
     * @param sql SQL语句
     * @param parameters SQL参数列表
     * @param conn 数据库连接
     */
    public static void analyze(String sql, List<Object> parameters, Connection conn) {
        if (!shouldAnalyze(sql)) {
            return;
        }

        // 检查SQL兼容性
        checkSqlCompatibility(sql);

        try {
            String explainableSql = SqlFormatter.createExplainableSql(sql, parameters);
            LOGGER.info("正在分析SQL: \n{}", explainableSql);
            
            // 设置当前正在分析的SQL
            CURRENT_ANALYZING_SQL.set(explainableSql);
            
            // 在索引分析日志中记录当前分析的SQL，不再区分是否为预编译SQL
            INDEX_ANALYSIS_LOGGER.info("===== 分析SQL =====\n{}", explainableSql);
            
            // 调用回调接口的onAnalysisStart方法
            if (CONFIG.hasCallback()) {
                CONFIG.getCallbackManager().notifyAnalysisStart(explainableSql);
            }
            
            // 仍然记录参数信息
            if (CONFIG.isPrintParameters() && !parameters.isEmpty()) {
                StringBuilder paramInfo = new StringBuilder("查询参数:\n");
                for (int i = 0; i < parameters.size(); i++) {
                    paramInfo.append("  参数 ").append(i + 1).append(": ")
                            .append(parameters.get(i)).append("\n");
                }
                LOGGER.info(paramInfo.toString());
            }

            // 根据MySQL版本使用不同的EXPLAIN格式
            String explainSql = SqlFormatter.getExplainSql(explainableSql, CONFIG.isMySQL80Mode() && CONFIG.isProvideOptimizationTips());

            try (Statement explainStmt = conn.createStatement();
                 ResultSet explainRs = explainStmt.executeQuery(explainSql)) {

                processExplainResult(explainRs);
            }
        } catch (SQLException e) {
            LOGGER.error("分析SQL时出错: {}", e.getMessage(), e);
            
            // 调用回调接口的onAnalysisError方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisError(originalSql, "分析SQL时出错: " + e.getMessage(), e);
            }
        } finally {
            // 清除ThreadLocal变量，防止内存泄漏
            CURRENT_ANALYZING_SQL.remove();
        }
    }

    /**
     * 检查SQL语句兼容性
     * @param sql SQL语句
     */
    public static void checkSqlCompatibility(String sql) {
        // 如果是5.7兼容模式，检查8.0特有语法
        if (CONFIG.isMySQL57Mode()) {
            if (SqlPatterns.containsMySQL80Feature(sql)) {
                String message = "SQL包含MySQL 8.0特有语法，在5.7环境中可能不兼容";
                LOGGER.warn(message);

                if (CONFIG.isStrictMode()) {
                    throw new MySQLVersionIncompatibleException(message);
                }
            }
        }
    }

    /**
     * 处理EXPLAIN结果
     * @param explainRs EXPLAIN结果集
     * @throws SQLException SQL异常
     */
    private static void processExplainResult(ResultSet explainRs) throws SQLException {
        // 检查是否为JSON格式结果
        if (CONFIG.isMySQL80Mode() && CONFIG.isProvideOptimizationTips()) {
            try {
                ResultSetMetaData metaData = explainRs.getMetaData();
                int columnCount = metaData.getColumnCount();

                // 在MySQL 8.0 EXPLAIN FORMAT=JSON结果中应该只有一个列
                if (columnCount == 1) {
                    if (explainRs.next()) {
                        String jsonResult = explainRs.getString(1);
                        if (jsonResult != null && jsonResult.startsWith("{")) {
                            processExplainJsonResult(jsonResult);
                            return;
                        }
                    }
                }
            } catch (SQLException e) {
                LOGGER.warn("解析JSON格式EXPLAIN结果失败，回退到标准格式: {}", e.getMessage());
                // 回退到标准处理方式
            }
        }

        // 标准EXPLAIN结果处理
        processStandardExplainResult(explainRs);
    }

    /**
     * 处理标准格式的EXPLAIN结果
     * @param explainRs EXPLAIN结果集
     * @throws SQLException SQL异常
     */
    private static void processStandardExplainResult(ResultSet explainRs) throws SQLException {
        if (CONFIG.isShowDetailedAnalysis()) {
            // 详细格式输出
            processDetailedStandardExplainResult(explainRs);
        } else {
            // 简洁JSON格式输出
            processSimpleStandardExplainResult(explainRs);
        }
    }

    /**
     * 处理标准格式的EXPLAIN结果 - 简洁输出
     * @param explainRs EXPLAIN结果集
     * @throws SQLException SQL异常
     */
    private static void processSimpleStandardExplainResult(ResultSet explainRs) throws SQLException {
        List<Object> tableInfoList = new ArrayList<>();

        while (explainRs.next()) {
            java.util.Map<String, Object> tableInfo = new java.util.HashMap<>();

            // 基本信息: table_name、access_type、key、ref
            tableInfo.put("table_name", explainRs.getString("table"));
            tableInfo.put("access_type", explainRs.getString("type"));

            String key = explainRs.getString("key");
            tableInfo.put("key", key != null && !key.isEmpty() ? key : null);

            String ref = explainRs.getString("ref");
            if (ref != null && !ref.isEmpty()) {
                List<String> refList = new ArrayList<>();
                for (String r : ref.split(",")) {
                    refList.add(r.trim());
                }
                tableInfo.put("ref", refList);
            } else {
                tableInfo.put("ref", null);
            }

            // 行数
            tableInfo.put("rows", explainRs.getInt("rows"));

            // 获取过滤率，如果有的话
            try {
                String filtered = explainRs.getString("filtered");
                if (filtered != null && !filtered.isEmpty()) {
                    tableInfo.put("filtered", filtered);
                }
            } catch (SQLException e) {
                // 某些MySQL版本可能没有filtered列，忽略异常
            }

            tableInfoList.add(tableInfo);
        }

        try {
            // 输出JSON格式结果
            ObjectMapper mapper = new ObjectMapper();
            String jsonResult = mapper.writeValueAsString(tableInfoList);

            // 使用普通Logger记录
            LOGGER.info("索引分析结果: {}", jsonResult);

            // 使用专用Logger将结果记录到单独的文件
            INDEX_ANALYSIS_LOGGER.info(jsonResult);
            
            // 调用回调接口的onAnalysisComplete方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisComplete(originalSql, jsonResult, true);
            }
        } catch (Exception e) {
            LOGGER.error("生成简洁标准分析报告时出错: {}", e.getMessage(), e);
            
            // 调用回调接口的onAnalysisError方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisError(originalSql, "生成简洁标准分析报告时出错: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 处理标准格式的EXPLAIN结果 - 详细输出
     * @param explainRs EXPLAIN结果集
     * @throws SQLException SQL异常
     */
    private static void processDetailedStandardExplainResult(ResultSet explainRs) throws SQLException {
        StringBuilder report = new StringBuilder("\n===== 索引使用分析 =====\n");

        while (explainRs.next()) {
            String type = explainRs.getString("type");
            String key = explainRs.getString("key");
            String table = explainRs.getString("table");
            String rows = explainRs.getString("rows");
            String extra = explainRs.getString("Extra");

            report.append("表: ").append(table).append("\n");
            report.append("扫描类型: ").append(type).append("\n");
            report.append("使用索引: ").append(key == null ? "无" : key).append("\n");
            report.append("扫描行数: ").append(rows).append("\n");
            report.append("额外信息: ").append(extra).append("\n");

            // 检查索引使用情况 - 判断全表扫描或低效索引
            if ("ALL".equals(type) || "index".equals(type) || key == null || key.isEmpty()) {
                report.append("警告: 该查询可能存在索引问题，");
                if ("ALL".equals(type)) {
                    report.append("正在进行全表扫描!\n");
                } else if (key == null || key.isEmpty()) {
                    report.append("未使用索引!\n");
                } else if ("index".equals(type)) {
                    report.append("正在使用索引进行全表扫描!\n");
                }

                // 提供可能的优化建议
                if (CONFIG.isProvideOptimizationTips() && extra != null && extra.contains("Using where")) {
                    addVersionSpecificTips(report, type, extra);
                }
            } else {
                report.append("索引使用正常\n");
            }
            report.append("----------------\n");
        }

        // 输出结果
        String reportStr = report.toString();
        LOGGER.info(reportStr);
        
        // 使用专用Logger将结果记录到单独的文件
        INDEX_ANALYSIS_LOGGER.info(reportStr);
        
        // 调用回调接口的onAnalysisComplete方法
        if (CONFIG.hasCallback()) {
            String originalSql = CURRENT_ANALYZING_SQL.get();
            CONFIG.getCallbackManager().notifyAnalysisComplete(originalSql, reportStr, false);
        }
    }

    /**
     * 处理JSON格式的EXPLAIN结果（MySQL 8.0特有）
     * @param jsonResult JSON格式结果
     */
    private static void processExplainJsonResult(String jsonResult) {
        try {
            // 使用Jackson解析JSON
            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readTree(jsonResult);

            // 根据配置决定输出简洁或详细分析
            if (CONFIG.isShowDetailedAnalysis()) {
                // 详细分析报告 - 保持原有逻辑
                processDetailedAnalysis(rootNode);
            } else {
                // 简洁的分析报告 - 只输出基本信息
                processSimpleAnalysis(rootNode);
            }

        } catch (IOException e) {
            LOGGER.error("解析JSON结果时出错: {}", e.getMessage(), e);
            LOGGER.debug("原始JSON: {}", jsonResult);
        }
    }

    /**
     * 处理简洁的分析报告，只输出基本的索引信息
     * @param rootNode JSON根节点
     */
    private static void processSimpleAnalysis(JsonNode rootNode) {
        try {
            // 使用Jackson解析JSON
            ObjectMapper mapper = new ObjectMapper();
            List<Object> tableInfoList = new ArrayList<>();

            // 解析查询计划
            JsonNode queryBlock = rootNode.path("query_block");
            if (!queryBlock.isMissingNode()) {
                // 处理单表查询
                JsonNode tableNode = queryBlock.path("table");
                if (!tableNode.isMissingNode()) {
                    tableInfoList.add(extractSimpleTableInfo(tableNode));
                }

                // 处理多表联查
                JsonNode nestedLoopNode = queryBlock.path("nested_loop");
                if (!nestedLoopNode.isMissingNode() && nestedLoopNode.isArray()) {
                    for (JsonNode joinNode : nestedLoopNode) {
                        JsonNode joinTableNode = joinNode.path("table");
                        if (!joinTableNode.isMissingNode()) {
                            tableInfoList.add(extractSimpleTableInfo(joinTableNode));
                        }
                    }
                }
            }

            // 输出简洁的JSON格式结果
            String jsonResult = mapper.writeValueAsString(tableInfoList);
            LOGGER.info("索引分析结果: {}", jsonResult);

            // 使用专用Logger将结果记录到单独的文件
            INDEX_ANALYSIS_LOGGER.info(jsonResult);
            
            // 调用回调接口的onAnalysisComplete方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisComplete(originalSql, jsonResult, true);
            }

        } catch (Exception e) {
            LOGGER.error("生成简洁分析报告时出错: {}", e.getMessage(), e);
            
            // 调用回调接口的onAnalysisError方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisError(originalSql, "生成简洁分析报告时出错: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 从表节点提取简洁的表信息
     * @param tableNode 表节点
     * @return 包含基本信息的Map
     */
    private static Object extractSimpleTableInfo(JsonNode tableNode) {
        java.util.Map<String, Object> tableInfo = new java.util.HashMap<>();

        // 基本信息: table_name、access_type、key、ref
        tableInfo.put("table_name", tableNode.path("table_name").asText("N/A"));
        tableInfo.put("access_type", tableNode.path("access_type").asText("N/A"));

        String keyName = tableNode.path("key").asText(null);
        tableInfo.put("key", keyName != null && !keyName.isEmpty() ? keyName : null);

        // 处理ref信息
        JsonNode refNode = tableNode.path("ref");
        if (refNode.isArray() && refNode.size() > 0) {
            List<String> refs = new ArrayList<>();
            for (JsonNode ref : refNode) {
                refs.add(ref.asText());
            }
            tableInfo.put("ref", refs);
        } else {
            tableInfo.put("ref", null);
        }

        // 添加行信息
        tableInfo.put("rows", tableNode.path("rows_examined_per_scan").asInt(0));
        tableInfo.put("filtered", tableNode.path("filtered").asText("100.00"));

        return tableInfo;
    }

    /**
     * 处理详细的分析报告，输出完整的索引分析信息
     * @param rootNode JSON根节点
     */
    private static void processDetailedAnalysis(JsonNode rootNode) {
        StringBuilder report = new StringBuilder("\n===== MySQL 8.0 详细索引分析 =====\n");

        // 解析查询计划
        JsonNode queryBlock = rootNode.path("query_block");
        if (!queryBlock.isMissingNode()) {
            // 添加基本信息
            report.append("查询ID: ").append(queryBlock.path("select_id").asText("N/A")).append("\n\n");

            // 处理表信息 - 单表查询
            JsonNode tableNode = queryBlock.path("table");
            if (!tableNode.isMissingNode()) {
                // 在处理表信息前，先获取表级别的成本信息
                JsonNode costInfo = tableNode.path("cost_info");
                if (!costInfo.isMissingNode()) {
                    report.append("成本信息: ");
                    report.append("读取成本=").append(costInfo.path("read_cost").asText("N/A")).append(", ");
                    report.append("评估成本=").append(costInfo.path("eval_cost").asText("N/A")).append(", ");
                    report.append("前缀成本=").append(costInfo.path("prefix_cost").asText("N/A")).append(", ");
                    report.append("每次连接读取数据=").append(costInfo.path("data_read_per_join").asText("N/A")).append("\n");

                    // 添加行信息
                    report.append("行信息: ");
                    report.append("每次扫描检查行数=").append(tableNode.path("rows_examined_per_scan").asText("N/A")).append(", ");
                    report.append("每次连接产生行数=").append(tableNode.path("rows_produced_per_join").asText("N/A")).append(", ");
                    report.append("过滤率=").append(tableNode.path("filtered").asText("N/A")).append("%\n\n");
                }

                processTableNode(report, tableNode);
            }

            // 处理嵌套循环连接 - 多表联查
            JsonNode nestedLoopNode = queryBlock.path("nested_loop");
            if (!nestedLoopNode.isMissingNode() && nestedLoopNode.isArray()) {
                report.append("\n多表联查信息:\n");
                report.append("=====================\n");

                // 多表查询的总体成本信息
                JsonNode queryBlockCostInfo = queryBlock.path("cost_info");
                if (!queryBlockCostInfo.isMissingNode()) {
                    report.append("联查总成本: ");
                    report.append("总成本=").append(queryBlockCostInfo.path("query_cost").asText("N/A")).append("\n\n");
                }

                int tableIndex = 1;
                for (JsonNode joinNode : nestedLoopNode) {
                    JsonNode joinTableNode = joinNode.path("table");
                    if (!joinTableNode.isMissingNode()) {
                        report.append("表 #").append(tableIndex++).append(":\n");

                        // 添加该表的成本信息
                        JsonNode tableCostInfo = joinTableNode.path("cost_info");
                        if (!tableCostInfo.isMissingNode()) {
                            report.append("表成本信息: ");
                            report.append("读取成本=").append(tableCostInfo.path("read_cost").asText("N/A")).append(", ");
                            report.append("评估成本=").append(tableCostInfo.path("eval_cost").asText("N/A")).append(", ");
                            report.append("前缀成本=").append(tableCostInfo.path("prefix_cost").asText("N/A")).append(", ");
                            report.append("每次连接读取数据=").append(tableCostInfo.path("data_read_per_join").asText("N/A")).append("\n");

                            // 添加行信息
                            report.append("行信息: ");
                            report.append("每次扫描检查行数=").append(joinTableNode.path("rows_examined_per_scan").asText("N/A")).append(", ");
                            report.append("每次连接产生行数=").append(joinTableNode.path("rows_produced_per_join").asText("N/A")).append(", ");
                            report.append("过滤率=").append(joinTableNode.path("filtered").asText("N/A")).append("%\n");
                        }

                        processTableNode(report, joinTableNode);

                        // 获取连接条件
                        JsonNode joinCondition = joinTableNode.path("join_condition");
                        if (!joinCondition.isMissingNode() && joinCondition.isArray() && joinCondition.size() > 0) {
                            report.append("连接条件: ");
                            List<String> conditions = new ArrayList<>();
                            for (JsonNode condition : joinCondition) {
                                conditions.add(condition.asText());
                            }
                            report.append(String.join(" AND ", conditions)).append("\n");
                        }

                        // 获取连接类型
                        String joinType = joinTableNode.path("join_type").asText(null);
                        if (joinType != null && !joinType.isEmpty()) {
                            report.append("连接类型: ").append(joinType).append("\n");
                        }

                        report.append("---------------------\n");
                    }
                }
                report.append("=====================\n");
            }

            // 处理排序信息
            JsonNode orderingOperation = queryBlock.path("ordering_operation");
            if (!orderingOperation.isMissingNode()) {
                report.append("排序操作:\n");
                report.append("  排序方法: ").append(orderingOperation.path("using_filesort").asBoolean() ? "文件排序" : "索引排序").append("\n");

                // 查看排序键
                JsonNode sortKeysNode = orderingOperation.path("sort_key");
                if (sortKeysNode.isArray()) {
                    report.append("  排序键: ");
                    List<String> sortKeys = new ArrayList<>();
                    for (JsonNode keyNode : sortKeysNode) {
                        sortKeys.add(keyNode.asText());
                    }
                    report.append(String.join(", ", sortKeys)).append("\n");
                }
                report.append("\n");
            }
        }

        // 检查是否有警告信息
        boolean hasWarning = false;
        StringBuilder warnings = new StringBuilder();

        // 检查全表扫描
        if (rootNode.toString().contains("\"access_type\": \"ALL\"")) {
            hasWarning = true;
            warnings.append("发现全表扫描! 这可能导致性能问题。\n");
        }

        // 检查临时表使用
        if (rootNode.toString().contains("\"using_temporary_table\": true")) {
            hasWarning = true;
            warnings.append("查询使用了临时表，可能需要优化。\n");
        }

        // 检查文件排序
        if (rootNode.toString().contains("\"using_filesort\": true")) {
            hasWarning = true;
            warnings.append("查询使用了文件排序，可能会影响性能。\n");
        }

        // 检查JOIN操作
        if (rootNode.toString().contains("\"nested_loop\"")) {
            // 不一定是警告，但需要注意
            if (!hasWarning) {  // 避免重复输出
                report.append("\n多表联查注意事项:\n");
                report.append("多表关联查询需要特别注意连接条件的索引优化。\n");
            }
        }

        // 如果有警告，添加优化建议
        if (hasWarning) {
            report.append("\n警告:\n").append(warnings);
            report.append("\n优化建议:\n");
            report.append("1. 检查查询中的WHERE条件字段是否有适当的索引\n");
            report.append("2. 对于ORDER BY和GROUP BY操作，考虑添加复合索引\n");
            report.append("3. 对于排序操作，尝试使用降序索引(MySQL 8.0+)或覆盖索引\n");

            // 对于多表联查的特别建议
            if (rootNode.toString().contains("\"nested_loop\"")) {
                report.append("4. 对于多表联查，确保连接字段在被驱动表上有索引\n");
                report.append("5. 考虑调整表的连接顺序，让小表作为驱动表\n");
                report.append("6. 使用STRAIGHT_JOIN强制优化器按指定顺序连接表\n");
            }

            report.append("7. 可以使用EXPLAIN FORMAT=TREE获取更易读的执行计划\n");
        } else {
            report.append("\n未发现明显性能问题，查询执行计划良好。\n");
        }

        try {
            // 输出结果
            String reportStr = report.toString();
            LOGGER.info(reportStr);
            
            // 使用专用Logger将结果记录到单独的文件
            INDEX_ANALYSIS_LOGGER.info(reportStr);
            
            // 调用回调接口的onAnalysisComplete方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisComplete(originalSql, reportStr, false);
            }
        } catch (Exception e) {
            LOGGER.error("生成详细分析报告时出错: {}", e.getMessage(), e);
            
            // 调用回调接口的onAnalysisError方法
            if (CONFIG.hasCallback()) {
                String originalSql = CURRENT_ANALYZING_SQL.get();
                CONFIG.getCallbackManager().notifyAnalysisError(originalSql, "生成详细分析报告时出错: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 处理表节点信息
     * @param report 报告构建器
     * @param tableNode 表节点
     */
    private static void processTableNode(StringBuilder report, JsonNode tableNode) {
        String tableName = tableNode.path("table_name").asText("N/A");
        String tableAlias = tableNode.path("table_alias").asText(null);

        report.append("表: ").append(tableName);
        if (tableAlias != null && !tableAlias.equals(tableName) && !tableAlias.isEmpty()) {
            report.append(" (别名: ").append(tableAlias).append(")");
        }
        report.append("\n");

        // 访问类型
        String accessType = tableNode.path("access_type").asText("N/A");
        report.append("访问类型: ").append(accessType);

        // 给出访问类型的具体解释
        report.append(" (");
        switch (accessType) {
            case "ALL":
                report.append("全表扫描，性能最差");
                break;
            case "index":
                report.append("全索引扫描，性能较差");
                break;
            case "range":
                report.append("范围扫描，性能中等");
                break;
            case "ref":
                report.append("非唯一索引查找，性能好");
                break;
            case "eq_ref":
                report.append("唯一索引查找，性能很好");
                break;
            case "const":
                report.append("常量查找，性能极好");
                break;
            case "system":
                report.append("系统表查找，性能最优");
                break;
            default:
                report.append("其他访问类型");
        }
        report.append(")\n");

        // 使用的索引
        String keyName = tableNode.path("key").asText(null);
        report.append("使用索引: ").append(keyName != null && !keyName.isEmpty() ? keyName : "无");

        // 对于可能的索引列表
        JsonNode possibleKeys = tableNode.path("possible_keys");
        if (possibleKeys.isArray() && possibleKeys.size() > 0) {
            List<String> keys = new ArrayList<>();
            for (JsonNode key : possibleKeys) {
                keys.add(key.asText());
            }
            report.append(" (可选索引: ").append(String.join(", ", keys)).append(")");
        }
        report.append("\n");

        // 索引使用情况分析
        if (keyName != null && !keyName.isEmpty()) {
            JsonNode keyLength = tableNode.path("key_length");
            if (!keyLength.isMissingNode()) {
                report.append("索引长度: ").append(keyLength.asText()).append("\n");
            }

            JsonNode usedKeyParts = tableNode.path("used_key_parts");
            if (usedKeyParts.isArray() && usedKeyParts.size() > 0) {
                List<String> parts = new ArrayList<>();
                for (JsonNode part : usedKeyParts) {
                    parts.add(part.asText());
                }
                report.append("使用的索引部分: ").append(String.join(", ", parts)).append("\n");
            }
        }

        // 扫描行数
        JsonNode rowsExamined = tableNode.path("rows_examined_per_scan");
        if (!rowsExamined.isMissingNode()) {
            report.append("扫描行数: ").append(rowsExamined.asText()).append("\n");
        }

        // 多表联查特有信息
        JsonNode accessType2 = tableNode.path("access_type_for_join");
        if (!accessType2.isMissingNode()) {
            report.append("连接访问类型: ").append(accessType2.asText()).append("\n");
        }

        // ref列信息 - 显示与哪些列进行了连接
        JsonNode refNode = tableNode.path("ref");
        if (refNode.isArray() && refNode.size() > 0) {
            List<String> refs = new ArrayList<>();
            for (JsonNode ref : refNode) {
                refs.add(ref.asText());
            }
            report.append("引用列: ").append(String.join(", ", refs)).append("\n");
        }

        // 过滤情况
        JsonNode filteredNode = tableNode.path("filtered");
        if (!filteredNode.isMissingNode()) {
            double filtered = filteredNode.asDouble(100.0);
            report.append("过滤率: ").append(filtered).append("%");

            if (filtered < 20.0) {
                report.append(" (注意: 低过滤率表明WHERE条件效率低)");
            } else if (filtered > 80.0) {
                report.append(" (良好: 高过滤率表明WHERE条件效率高)");
            }
            report.append("\n");
        }

        // 附加信息
        List<String> attachedInfo = new ArrayList<>();

        if (tableNode.path("using_index").asBoolean(false)) {
            attachedInfo.add("Using index (仅使用索引，无需回表)");
        }

        if (tableNode.path("using_where").asBoolean(false)) {
            attachedInfo.add("Using where (使用WHERE过滤)");
        }

        if (tableNode.path("using_temporary_table").asBoolean(false)) {
            attachedInfo.add("Using temporary (使用临时表，性能较差)");
        }

        if (tableNode.path("using_filesort").asBoolean(false)) {
            attachedInfo.add("Using filesort (使用文件排序，性能较差)");
        }

        // 联查特有标记
        if (tableNode.path("using_join_buffer").asBoolean(false)) {
            String bufferType = tableNode.path("join_buffer_type").asText("unknown");
            attachedInfo.add("Using join buffer (" + bufferType + ")");
        }

        if (!attachedInfo.isEmpty()) {
            report.append("附加信息: ").append(String.join(", ", attachedInfo)).append("\n");
        }

        // 分析可能的问题
        boolean problemFound = false;

        // 查询类型特定分析
        if ("ALL".equals(accessType)) {
            problemFound = true;
            report.append("警告: 正在进行全表扫描! 考虑为查询条件添加适当的索引\n");
        } else if ("index".equals(accessType)) {
            problemFound = true;
            report.append("警告: 正在使用索引进行全表扫描! 考虑修改查询或添加针对性索引\n");
        } else if (keyName == null || keyName.isEmpty()) {
            problemFound = true;
            report.append("警告: 未使用索引! 考虑为WHERE/JOIN子句中的字段创建索引\n");
        }

        // 多表联查特定分析
        JsonNode joinType = tableNode.path("join_type");
        if (!joinType.isMissingNode()) {
            String type = joinType.asText();
            if ("ALL".equals(type)) {
                problemFound = true;
                report.append("警告: 该表在连接中使用了扫描方式! 为连接字段添加索引\n");
            }
        }

        // 检查是否是"驱动表"或"被驱动表"
        if (tableNode.path("first_match_tab").asInt(-1) != -1) {
            report.append("信息: 此表是子查询的驱动表\n");
        }

        if (!problemFound) {
            report.append("索引使用正常\n");
        }
    }

    /**
     * 添加版本特定的优化建议
     * @param report 报告构建器
     * @param type 扫描类型
     * @param extra 额外信息
     */
    private static void addVersionSpecificTips(StringBuilder report, String type, String extra) {
        report.append("建议: 考虑为WHERE子句中的字段创建索引\n");

        if (CONFIG.isMySQL80Mode()) {
            // MySQL 8.0特有的优化建议
            report.append("MySQL 8.0提示: ");

            if (extra.contains("Using filesort")) {
                report.append("考虑使用降序索引或函数索引改进排序性能\n");
            } else if (extra.contains("Using temporary")) {
                report.append("考虑使用多列索引或函数索引优化GROUP BY或DISTINCT操作\n");
            } else {
                report.append("考虑使用不可见索引进行索引测试，或使用OPTIMIZER_SWITCH调整优化器行为\n");
            }
        } else if (CONFIG.isMySQL57Mode()) {
            // MySQL 5.7特有的优化建议
            report.append("MySQL 5.7提示: ");

            if (extra.contains("Using filesort")) {
                report.append("考虑调整索引顺序以匹配ORDER BY子句\n");
            } else if (extra.contains("Using temporary")) {
                report.append("考虑创建复合索引包含GROUP BY或ORDER BY中的所有列\n");
            } else {
                report.append("考虑使用索引提示(USE INDEX, FORCE INDEX)指导优化器的选择\n");
            }
        }
    }

    /**
     * 判断是否应该分析该SQL
     * @param sql SQL语句
     * @return 是否应该分析
     */
    private static boolean shouldAnalyze(String sql) {
        if (!CONFIG.isEnabled()) {
            return false;
        }

        if (sql == null) {
            return false;
        }

        sql = sql.trim();

        // 检查SQL是否匹配忽略规则
        if (CONFIG.isUseIgnorePatterns() && CONFIG.matchesIgnorePatterns(sql)) {
            LOGGER.debug("SQL匹配忽略规则，将跳过分析: {}", sql);
            return false;
        }

        // 使用SqlPatterns类检查是否为简单测试SQL
        if (SqlPatterns.isSimpleTestSql(sql)) {
            return false;
        }
        
        // 检查是否有自定义SQL检测规则，且SQL匹配这些规则
        if (CONFIG.isUseCustomPatterns() && CONFIG.matchesCustomPatterns(sql)) {
            LOGGER.debug("SQL匹配自定义检测规则，将进行分析: {}", sql);
            return true;
        }

        // 检查是否需要只分析SELECT语句
        if (CONFIG.isSelectOnly()) {
            return SqlPatterns.isSelectStatement(sql);
        }

        return true;
    }

    /**
     * MySQL版本不兼容异常
     */
    public static class MySQLVersionIncompatibleException extends RuntimeException {
        public MySQLVersionIncompatibleException(String message) {
            super(message);
        }
    }
}
